package com.macro.mall.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * @author by jicai on 2019/8/28.
 */
@Slf4j
public class EncryptionUtil {

    private static final String DEFAULT_CIPHER_ALGORITHM        = "AES/CBC/PKCS5Padding";

    private static final String KEY_ALGORITHM                    = "AES";

    private static SecretKeySpec SECRET_KEY_SPEC;

    private static IvParameterSpec IV_PARAMETER_SPEC;


    private EncryptionUtil() {
    }

    private static Cipher initCipher(int type) {
        Cipher cipher = null;
        try {
            // 创建密码器
            cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            // 初始化为某种模式的密码器ENCRYPT_MODE/DECRYPT_MODE/WRAP_MODE/UNWRAP_MODE/PUBLIC_KEY/PRIVATE_KEY
            cipher.init(type, SECRET_KEY_SPEC, IV_PARAMETER_SPEC);
        } catch (Exception e) {
            log.error("AES初始化失败, info:" + e.toString());
        }
        return cipher;
    }

    /**
     * 加密初始化
     *
     * @param password 密码
     * @param iv       向量
     */
    public static void initEncryptionInfo(String password, String iv) {
        try {
            IV_PARAMETER_SPEC = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
            // 转换为AES专用密钥
            SECRET_KEY_SPEC = new SecretKeySpec(password.getBytes(), KEY_ALGORITHM);
        } catch (Exception ex) {
            log.error("AES工具初始化秘钥和向量失败, info:" + ex.toString());
        }

        log.info("AES加密初始化");
    }

    /**
     * AES 解密操作
     *
     * @param content 密文
     * @return 内容
     */
    public static Long aesDecrypt(String content) {
        //替换特殊字符
        try {
            return Long.parseLong(new String(initCipher(Cipher.DECRYPT_MODE).doFinal(Base64.decodeBase64(content))));
        } catch (Exception ex) {
            log.error("AES解密失败, info:" + ex.toString());
        }
        return null;
    }

    /**
     * AES 加密操作
     *
     * @param accountId 待加密内容
     * @return 返回Base64转码后的加密数据
     */
    public static String aesEncrypt(Long accountId) {
        String encryptContent = null;

        try {
            //初始化密码器
            encryptContent = Base64.encodeBase64String(initCipher(Cipher.ENCRYPT_MODE).doFinal(accountId.toString().getBytes(
                    StandardCharsets.UTF_8)));
            //替换特殊字符
        } catch (Exception ex) {
            log.error("AES加密失败, info:" + ex.toString());
        }
        return encryptContent;
    }
}
